#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>

void daemonize() {
    pid_t pid;
    
    // 步骤1: 创建子进程并终止父进程
    pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {  // 父进程退出
        exit(EXIT_SUCCESS);
    }
    
    // 步骤2: 创建新会话 - 脱离终端
    if (setsid() < 0) {
        perror("setsid failed");
        exit(EXIT_FAILURE);
    }
    
    // 步骤3: (可选但推荐) 二次fork确保不是会话首进程
    pid = fork();
    if (pid < 0) {
        perror("second fork failed");
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {  // 第一次的子进程退出
        exit(EXIT_SUCCESS);
    }
    
    // 步骤4: 更改工作目录到根目录
    if (chdir("/") < 0) {
        perror("chdir failed");
        exit(EXIT_FAILURE);
    }
    
    // 步骤5: 重设文件权限掩码
    umask(0);
    
    // 步骤6: 关闭所有打开的文件描述符
    for (int fd = sysconf(_SC_OPEN_MAX); fd >= 0; fd--) {
        close(fd);
    }
    
    // 步骤7: 重定向标准输入/输出/错误到/dev/null
    int null_fd = open("/dev/null", O_RDWR);
    if (null_fd < 0) {
        perror("open /dev/null failed");
        exit(EXIT_FAILURE);
    }
    
    dup2(null_fd, STDIN_FILENO);   // 标准输入 -> /dev/null
    dup2(null_fd, STDOUT_FILENO);  // 标准输出 -> /dev/null
    dup2(null_fd, STDERR_FILENO);  // 标准错误 -> /dev/null
    
    // 如果原始描述符不是标准流，关闭它
    if (null_fd > STDERR_FILENO) {
        close(null_fd);
    }
    
    // 步骤8: 使用syslog记录日志
    openlog("mydaemon", LOG_PID, LOG_DAEMON);
    syslog(LOG_INFO, "Daemon started successfully");
}

int main() {
    daemonize();
    
    // 守护进程主循环
    while (1) {
        // 实际服务逻辑
        syslog(LOG_INFO, "Daemon is running");
        sleep(60);  // 每分钟记录一次
    }
    
    closelog();
    return EXIT_SUCCESS;
}
